package cn.mw.cmdb.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.mw.cmdb.entity.AlgorithmInfo;
import cn.mw.cmdb.entity.DataSourceInfo;
import cn.mw.cmdb.entity.ModelGroupInfo;
import cn.mw.cmdb.entity.ModelInfo;
import cn.mw.cmdb.enums.*;
import cn.mw.cmdb.exception.CompoundException;
import cn.mw.cmdb.exception.DataUniqueException;
import cn.mw.cmdb.exception.InputRequireException;
import cn.mw.cmdb.mongoMapper.AlgorithmInfoMapper;
import cn.mw.cmdb.param.AlgorithmIdsParam;
import cn.mw.cmdb.param.AlgorithmSearchParam;
import cn.mw.cmdb.param.CalculatedMetricDTO;
import cn.mw.cmdb.param.TimeRangeDTO;
import cn.mw.cmdb.service.AlgorithmInfoService;
import cn.mw.cmdb.util.BaseUtil;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.cmdb.util.CronUtil;
import cn.mw.components.mongodb.entity.SearchParam;
import cn.mw.components.mongodb.entity.SubCondition;
import cn.mw.components.mongodb.exception.BusinessException;
import cn.mw.components.mongodb.tool.CriteriaWrapper;
import cn.mw.log.enums.BusinessLogType;
import cn.mw.log.enums.LogLevel;
import cn.mw.microMonitorCommon.api.powerjob.PowerJobRequestParam;
import cn.mw.microMonitorCommon.api.powerjob.PowerJobService;
import cn.mw.microMonitorCommon.constant.Constants;
import cn.mw.microMonitorCommon.entity.common.PowerJobAppInfoDTO;
import cn.mw.microMonitorCommon.operatorlog.client.MwLogClientSimple;
import cn.mw.microMonitorCommon.security.utils.SecurityUtils;
import cn.mw.microMonitorCommon.util.DateUtils;
import cn.mw.microMonitorCommon.util.IDModelType;
import cn.mw.microMonitorCommon.util.ModuleIDManager;
import com.alibaba.fastjson2.JSON;
import com.mongodb.client.result.DeleteResult;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
public class AlgorithmInfoServiceImpl extends ModelBaseServiceImpl<AlgorithmInfo, Object> implements AlgorithmInfoService {

    public static final String ID = "algorithmInfoService";

    public static final String SPACE = " ";
    public static final String SPLIT = ";";
    public static final String DateFormat = "yyyy-MM-dd HH:mm:ss";

    public static final String TASK_PROCESSOR = "mwAlgorithmProcessor";

    private CmdbServiceManage cmdbServiceManage;

    private AlgorithmInfoMapper algorithmInfoMapper;

    private ModuleIDManager moduleIDManager;

    private PowerJobService powerJobService;


    public AlgorithmInfoServiceImpl(CmdbServiceManage cmdbServiceManage, AlgorithmInfoMapper algorithmInfoMapper,
                                    ModuleIDManager moduleIDManager, PowerJobService powerJobService) {
        this.cmdbServiceManage = cmdbServiceManage;
        this.algorithmInfoMapper = algorithmInfoMapper;
        this.moduleIDManager = moduleIDManager;
        this.powerJobService = powerJobService;
    }
    private MwLogClientSimple logClientSimple;

    public AlgorithmInfoServiceImpl() {
         this.logClientSimple = SpringUtil.getBean(MwLogClientSimple.class);
    }

    @Override
    public String algorithm(AlgorithmInfo param) {
        String type = param.getType();
        String ret = AlgorithmEnum.getAlgorithmEnum(type).generatorAlgorithm(this, param);
        log.info("计算公式为：{}", ret);
        return ret;
    }

    public List<AlgorithmInfo> doSelectListByIds(Collection<String> ids) throws Exception {
        Query query = new Query();
        Criteria criteria = CriteriaWrapper.where(AlgorithmInfo::getId).in(ids);
        query.addCriteria(criteria);
        return algorithmInfoMapper.find(query);
    }

    /**
     * 繁忙度计算
     * （cpu最大利用率+磁盘平均值+...）/ n[选择了哪几个计算指标]
     *
     * @param param 参数对象
     * @return 繁忙度计算结果公式
     */
    public String calculationBusyness(AlgorithmInfo param) {
        Map<String, Object> dataMetric = param.getDataMetric();
        List<CalculatedMetricDTO> busynessMetricList = JSON.parseArray(JSON.toJSONString(dataMetric.get(AlgorithmEnum.busyness.getEnglishName())), CalculatedMetricDTO.class);
        if (CollUtil.isEmpty(busynessMetricList)) {
            return "";
        }
        StringBuilder sb = new StringBuilder("(");
        for (CalculatedMetricDTO calculatedMetric : busynessMetricList) {
            // 资源名
            String resourceUtilization = BusynessSystemUtilizationEnum.getCNameByEName(calculatedMetric.getResourceUtilization()).getChineseName();
            // 统计单位
            String statisticalValues = BusynessStatisticalEnum.getCNameByEName(calculatedMetric.getStatisticalValues()).getChineseName();
            sb.append(resourceUtilization).append(statisticalValues).append("+");
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append(")").append(SPACE).append("/").append(SPACE).append(busynessMetricList.size());
        return sb.toString();
    }

    /**
     * 可用性计算
     *
     * @param info 参数对象
     * @return 可用性计算结果公式 时间范围内的状态为1的总数 / 总状态数量 * 100%
     */
    public String calculationAvailability(AlgorithmInfo info) {
        Map<String, Object> dataMetric = info.getDataMetric();
        List<String> list = (List<String>) dataMetric.get(AlgorithmEnum.availability.getEnglishName());
        List<String> cList = new ArrayList<>();
        for (String s : list) {
            String chineseName = AlgorithmAvailableEnum.getAlgorithmAvailableByEName(s).getChineseName();
            cList.add(chineseName);
        }
        String join = String.join("+", cList);
        return "计算区间时间范围内的%s为1的总数".formatted(join) + SPACE +
                "/" + SPACE +
                "%s数量".formatted(join) + SPACE +
                "*" + SPACE + "100%";
    }

    /**
     * 健康度计算
     *
     * @param param 参数对象
     * @return 健康度计算结果公式
     */
    @SneakyThrows
    public String calculationHealthiness(AlgorithmInfo param) {
        List<TimeRangeDTO> timeRangeDTOS = getRangeDTOList(param.getCalculationInterval());
        List<TimeRangeDTO> timeRangeList = mergeIntervals(timeRangeDTOS);
        if (CollUtil.isEmpty(timeRangeList)) {
            return "";
        }
        return builderCalculatedHealthinessMethod(timeRangeList, param.getCalculationPeriod(), param.getCalculationPeriodUnit());

    }

    private List<TimeRangeDTO> getRangeDTOList(List<AlgorithmInfo.CalculationIntervalTime> calculationInterval) {
        List<TimeRangeDTO> timeRangeDTOS = new ArrayList<>();
        for (AlgorithmInfo.CalculationIntervalTime calculationIntervalTime : calculationInterval) {
            List<String> lists = calculationIntervalTime.getRange();
            TimeRangeDTO timeRangeDTO = new TimeRangeDTO(lists.get(0), lists.get(1));
            timeRangeDTOS.add(timeRangeDTO);
        }
        return timeRangeDTOS;
    }

    private String builderCalculatedHealthinessMethod(List<TimeRangeDTO> timeRangeList, Integer calculationPeriod, String calculationPeriodUnit) {
        StringBuilder sb = new StringBuilder("1 - (");
        for (TimeRangeDTO interval : timeRangeList) {
            String timePeriod = interval.getStartTime() + "-" + interval.getEndTime();
            sb.append("(").append(timePeriod).append(")").append("+");
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append(SPACE).append("/").append(SPACE).append(calculationPeriod).append(calculationPeriodUnit).append(")");
        sb.append(" * 100%");
        return sb.toString();
    }

    @SneakyThrows
    public static List<TimeRangeDTO> mergeIntervals(List<TimeRangeDTO> intervals) {
        // 将时间段按照开始时间排序
        intervals.sort(Comparator.comparing(interval -> {
            try {
                return new SimpleDateFormat(DateFormat).parse(interval.getStartTime());
            } catch (ParseException e) {
                e.printStackTrace();
                log.error("开始时间解析异常：{}, 异常原因：{}", interval.getStartTime(), e.toString());
                return null;
            }
        }));

        List<TimeRangeDTO> mergedIntervals = new ArrayList<>();
        TimeRangeDTO currentInterval = null;

        for (TimeRangeDTO interval : intervals) {
            if (currentInterval == null || isAfter(interval.getStartTime(), currentInterval.getEndTime())) {
                // 如果当前时间段为空或者新时间段的开始时间大于当前时间段的结束时间，则添加新时间段
                currentInterval = interval;
                mergedIntervals.add(interval);
            } else {
                // 否则，更新当前时间段的结束时间
                String endTime = laterTime(interval.getEndTime(), currentInterval.getEndTime());
                currentInterval.setEndTime(endTime);
            }
        }

        return mergedIntervals;
    }

    // 检查时间字符串1是否在时间字符串2之后
    private static boolean isAfter(String time1, String time2) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(DateFormat);
        Date date1 = sdf.parse(time1);
        Date date2 = sdf.parse(time2);
        return date1.after(date2);
    }

    // 返回两个时间字符串中较晚的时间
    private static String laterTime(String time1, String time2) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(DateFormat);
        Date date1 = sdf.parse(time1);
        Date date2 = sdf.parse(time2);
        return date1.after(date2) ? time1 : time2;
    }

    @Override
    public AlgorithmInfo genObject() {
        return new AlgorithmInfo();
    }

    @Override
    public Object doAdd(AlgorithmInfo param) throws Exception {
        String type = param.getType();
        if (StringUtils.isEmpty(type)) {
            throw new InputRequireException(new Object[]{type});
        }
        Criteria criteria = CriteriaWrapper
                .where(AlgorithmInfo::getAlgorithmName)
                .is(param.getAlgorithmName())
                .and(CMDBTool.getFieldName(AlgorithmInfo::getType)).is(type);

        Query query = new Query(criteria);
        Object one = algorithmInfoMapper.findOne(query);
        if (ObjectUtils.isNotEmpty(one)) {
            CompoundException instanceParamValidateException = new CompoundException();
            instanceParamValidateException.addInstanceValidateException(new DataUniqueException(new Object[]{param.getAlgorithmName()}));
            throw instanceParamValidateException;
        }
        AlgorithmEnum.getAlgorithmEnum(type).saveInfoByType(this, param);
        String cronString = genCronExpression(param);
        log.info("新建算法名:{}, cron: {}", param.getAlgorithmName(), cronString);
        param.setCalculationMethod(algorithm(param));
        param.setCronExpression(cronString);
        param.setCreateTime(BaseUtil.getNowLocalTime());
        param.setCreater(SecurityUtils.getUserId());
        String idStr = moduleIDManager.getIDStr(IDModelType.Algorithm);
        param.setId(idStr);

        if (ApplicationScopeEnum.global.name().equals(param.getApplicationScope())) {
            validatedDataScope(param);
            List<Long> jobTask = createJobTask(param, "");
            if (CollUtil.isNotEmpty(jobTask)) {
                param.setJobIds(jobTask);
            }
            algorithmInfoMapper.insert(param);
            return true;
        }
        // 自定义算法
        List<String> idProperties = getCustomModelIdProperties(param.getModelGroupOrIdList());
        param.setModelIdList(idProperties);
        List<Long> jobTask = createJobTask(param, "");
        if (CollUtil.isNotEmpty(jobTask)) {
            param.setJobIds(jobTask);
        }
        algorithmInfoMapper.insert(param);
        return true;
    }

    private void validatedDataScope(AlgorithmInfo param) throws Exception {
        Criteria scopeCriteria = CriteriaWrapper.where(CMDBTool.getFieldName(AlgorithmInfo::getType))
                .is(param.getType())
                .and(CMDBTool.getFieldName(AlgorithmInfo::getApplicationScope)).is(ApplicationScopeEnum.global.name());
        if (StrUtil.isNotBlank(param.getId())) {
            scopeCriteria.and(CMDBTool.getFieldName(AlgorithmInfo::getId)).ne(param.getId());
        }
        List<Object> objectList = algorithmInfoMapper.find(new Query(scopeCriteria));
        if (CollUtil.isNotEmpty(objectList)) {
            CompoundException instanceParamValidateException = new CompoundException();
            instanceParamValidateException.addInstanceValidateException(new DataUniqueException(new Object[]{param.getApplicationScope()}));
            throw instanceParamValidateException;
        }
    }

    @Override
    @Transactional
    public boolean doUpdate(AlgorithmInfo param) throws Exception {
        String type = param.getType();
        if (StringUtils.isEmpty(type)) {
            throw new InputRequireException(new Object[]{type});
        }
        AlgorithmEnum.getAlgorithmEnum(type).updateInfoByType(this, param);
        Criteria criteria = CriteriaWrapper.where(AlgorithmInfo::getAlgorithmName).is(param.getAlgorithmName())
                .and(CMDBTool.getFieldName(AlgorithmInfo::getId)).ne(param.getId());
        Query query = new Query(criteria);
        AlgorithmInfo existsInfo = algorithmInfoMapper.findOne(query);
        if (ObjectUtils.isNotEmpty(existsInfo)) {
            CompoundException instanceParamValidateException = new CompoundException();
            instanceParamValidateException.addInstanceValidateException(new DataUniqueException(new Object[]{param.getAlgorithmName()}));
            throw instanceParamValidateException;
        }
        // 获取数据库中该条任务的JOB ID
        query = new Query(CriteriaWrapper.where(AlgorithmInfo::getId).is(param.getId()));
        existsInfo = algorithmInfoMapper.findOne(query);
        if (ObjectUtils.isEmpty(existsInfo)) {
            throw new CompoundException();
        }
        List<Long> jobIds = existsInfo.getJobIds();
        String cronExpression = genCronExpression(param);
        log.info("更新算法名:{}, cron: {}", param.getAlgorithmName(), cronExpression);
        existsInfo.setCalculationMethod(algorithm(param));
        existsInfo.setModifier(SecurityUtils.getUserId());
        existsInfo.setModificationTime(BaseUtil.getNowLocalTime());
        existsInfo.setAlgorithmName(param.getAlgorithmName());
        existsInfo.setDataMetric(param.getDataMetric());
        existsInfo.setCalculationPeriodUnit(param.getCalculationPeriodUnit());
        existsInfo.setCalculationPeriod(param.getCalculationPeriod());
        existsInfo.setCalculationInterval(param.getCalculationInterval());
        existsInfo.setCalculationMethod(param.getCalculationMethod());
        existsInfo.setApplicationScope(param.getApplicationScope());
        existsInfo.setCronExpression(cronExpression);
        if (ApplicationScopeEnum.custom.name().equals(param.getApplicationScope())) {
            List<String> idProperties = getCustomModelIdProperties(param.getModelGroupOrIdList());
            existsInfo.setModelIdList(idProperties);
        } else {
            validatedDataScope(param);
        }
        String newCronExpression = getLastCronExpression(cronExpression, jobIds);
        if (StringUtils.isNotBlank(newCronExpression)) {
            List<Long> jobTaskId = createJobTask(existsInfo, newCronExpression);
            existsInfo.setJobIds(jobTaskId);
        }
        query = new Query(CriteriaWrapper.where(DataSourceInfo::getId).is(param.getId()));
        Update update = CMDBTool.genMongoUpdate(existsInfo, null, null);
        CMDBTool.updateFirst(algorithmInfoMapper, query, update);
        return true;
    }

    @NotNull
    private String getLastCronExpression(String cronExpression, List<Long> jobIds) {
        String newCronExpression = "";
        if (null != jobIds) {
            Map<Long, String> jobIdMap = new HashMap<>();

            List<PowerJobAppInfoDTO> jobDataList = powerJobService.getJobTaskByIds(jobIds).getData();
            if (CollUtil.isNotEmpty(jobDataList)) {
                // 当前生成的cron list
                List<String> currentJobCronList = Arrays.stream(cronExpression.split(SPLIT)).toList();
                // powerJob list 转为 map  <id, cronExpression>
                for (PowerJobAppInfoDTO infoDTO : jobDataList) {
                    // 不用判断是否为cron类型，因为创建的时候就时cron
                    jobIdMap.put(infoDTO.getId(), infoDTO.getTimeExpression());
                }
                List<String> list = jobIdMap.values().stream().toList();
                // 记录匹配的ID
                Set<Long> matchedIds = new HashSet<>();
                // 记录未匹配的表达式
                Set<String> unmatchedCronList = new HashSet<>();
                // 遍历currentJobCronList， 检查是否与 jobIdMap 中的表达式匹配
                for (String cron : currentJobCronList) {
                    boolean flag = false;
                    for (Map.Entry<Long, String> entry : jobIdMap.entrySet()) {
                        if (containsCron(cron, list)) {
                            matchedIds.add(entry.getKey());
                            flag = true;
                            break;
                        }
                    }
                    if (!flag) {
                        // 如果未匹配，则记录新建
                        unmatchedCronList.add(cron);
                    }
                }
                // 所有的JOB id
                Set<Long> deleteIds = jobIdMap.keySet();
                // 匹配的matchedIds job id. long 过滤  matchedIds中的值。剩余的值删除

                if (CollUtil.isNotEmpty(deleteIds)) {
                    powerJobService.deleteJob(new ArrayList<>(matchedIds));
                }
                // 更次与之前相同 newCronExpressionList 就为空
                newCronExpression = String.join(SPLIT, unmatchedCronList);
            }
        }
        return StrUtil.isNotBlank(newCronExpression) ? newCronExpression : cronExpression;
    }

    public boolean containsCron(String cronExpression, List<String> powerJobCronList) {
        for (String powerCron : powerJobCronList) {
            if (cronExpression.contains(powerCron)) {
                return true;
            }
        }
        return false;
    }

    private List<String> getCustomModelIdProperties(List<List<String>> modelLists) throws Exception {
        if (CollUtil.isEmpty(modelLists)) {
            throw new CompoundException();
        }
        // 获取相关组信息
        ModelGroupServiceImpl modelService = (ModelGroupServiceImpl) cmdbServiceManage.getModelService(ModelGroupServiceImpl.ID);
        // 查询所有的组
        List<ModelGroupInfo> modelGroupInfos = modelService.selectList(new SearchParam());
        Set<String> modelIds = new HashSet<>();

        // 组ID转MAP与modelIdList匹配
        if (CollUtil.isNotEmpty(modelGroupInfos)) {
            Map<String, ModelGroupInfo> modelIdMap = modelGroupInfos.stream().collect(Collectors.toMap(ModelGroupInfo::getId, Function.identity()));
            List<String> modelIdOrGroupList = new ArrayList<>();
            for (List<String> list : modelLists) {
                String id = list.get(list.size() - 1);
                modelIdOrGroupList.add(id);
            }
            List<String> modelIdList = new ArrayList<>();
            List<String> modelIdGroupList = new ArrayList<>();
            for (String groupId : modelIdOrGroupList) {
                ModelGroupInfo modelGroupInfo = modelIdMap.get(groupId);
                if (null == modelGroupInfo) {
                    modelIdList.add(groupId);
                    continue;
                }
                modelIdGroupList.add(groupId);
            }
            // 组ID查模型ID
            CustomModelServiceImpl customModelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
            if (CollUtil.isNotEmpty(modelIdGroupList)) {
                List<ModelInfo> modelListByGroups = customModelService.findModelListByGroups(modelIdGroupList);
                if (CollUtil.isNotEmpty(modelListByGroups)) {
                    List<String> list = modelListByGroups.stream().map(ModelInfo::getId).toList();
                    modelIds.addAll(list);
                }
            }
            if (CollUtil.isNotEmpty(modelIdList)) {
                List<ModelInfo> modelListByIds = customModelService.findByIds(modelIdList);
                if (CollUtil.isNotEmpty(modelListByIds)) {
                    List<String> list = modelListByIds.stream().map(ModelInfo::getId).toList();
                    modelIds.addAll(list);
                }
            }
        }
        return new ArrayList<>(modelIds);
    }

    private String genCronExpression(AlgorithmInfo param) {
        List<TimeRangeDTO> calculationIntervalList = getRangeDTOList(param.getCalculationInterval());
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern(DateFormat);
        List<String> cronList = new ArrayList<>();
        calculationIntervalList.forEach(interval -> {
            LocalDateTime startTime = LocalDateTime.parse(interval.getStartTime(), pattern);
            LocalDateTime endTime = LocalDateTime.parse(interval.getEndTime(), pattern);
            DateUnitEnum dateUnitEnum = DateUnitEnum.getDateUnitEnumByEName(param.getCalculationPeriodUnit());
            if (null != dateUnitEnum) {
                String cron = CronUtil.generateCronExpressionByDateRange(startTime, endTime, param.getCalculationPeriod(), dateUnitEnum);
                cronList.add(cron);
            }
        });
        return String.join(SPLIT, cronList);
    }

    @Override
    boolean doRemove(AlgorithmInfo params) throws Exception {
        return false;
    }

    @Override
    Object doBatchAdd(Object params) throws Exception {
        return null;
    }

    @Override
    boolean doBatchUpdate(Object params) throws Exception {
        return false;
    }

    @Override
    AlgorithmInfo doSelectById(Object id) throws Exception {
        return null;
    }

    @Override
    List<AlgorithmInfo> doSelectList(Object param) throws Exception {
        AlgorithmSearchParam searchParam = (AlgorithmSearchParam) param;
        Map<String, SubCondition> condition = searchParam.getCondition();
        String applicationScopeKey = CMDBTool.getFieldName(AlgorithmInfo::getApplicationScope);
        if (condition.containsKey(applicationScopeKey)) {
            SubCondition subCondition = condition.get(applicationScopeKey);
            String value = ApplicationScopeEnum.getApplicationScopeEnumByDesc((String) subCondition.getValue());
            subCondition.setValue(value);
            condition.put(applicationScopeKey, subCondition);
        }

        Query query = genQuery(searchParam, null);
        Sort sort = searchParam.getSort();
        query.with(sort);
        List<AlgorithmInfo> ret = CMDBTool.selectList(AlgorithmInfo.class, algorithmInfoMapper, query, searchParam);
        return ret;
    }

    @Override
    @Transactional
    public boolean doBatchRemove(Object params) throws Exception {
        AlgorithmIdsParam param = (AlgorithmIdsParam) params;
        Query query = new Query(CriteriaWrapper.where(AlgorithmInfo::getId).in(param.getIds()));
        List<AlgorithmInfo> ret = CMDBTool.selectList(AlgorithmInfo.class, algorithmInfoMapper, query, null);

        DeleteResult remove = algorithmInfoMapper.remove(query);
        if (remove.getDeletedCount() > 0) {
            List<Long> jobIds = new ArrayList<>();
            for (AlgorithmInfo info : ret) {
                List<Long> jIds = info.getJobIds();
                if (CollUtil.isNotEmpty(jIds)) {
                    jobIds.addAll(jIds);
                }
            }
            if (CollUtil.isNotEmpty(jobIds)) {
                log.info("开始删除powerJob任务");
                powerJobService.deleteJob(jobIds);
            }
        }
        log.info("删除成功...");
        return true;
    }

    private List<Long> createJobTask(AlgorithmInfo param, String cronExpressions) {
        if (StrUtil.isBlank(cronExpressions)) {
            cronExpressions = param.getCronExpression();
        }
        log.info("开始调用powerJob, 创建定时任务....");
        if (StringUtils.isEmpty(param.getCronExpression())) {
            log.info("未找到cron表达式");
            return new ArrayList<>();
        }
        List<PowerJobRequestParam> paramList = new ArrayList<>();
        int jobCount = 1;
        for (String cronExpression : cronExpressions.split(SPLIT)) {
            PowerJobRequestParam jobParams = getJobParams(param, cronExpression, jobCount);
            paramList.add(jobParams);
            jobCount++;
        }
        List<Long> jobIdList = powerJobService.batchSaveOrUpdateJob(paramList).getData();
        jobIdList = jobIdList.stream().filter(Objects::nonNull).toList();
        if (CollUtil.isEmpty(jobIdList)) {
            log.error("创建定时任务异常, 任务类型：{}, 任务名称：{}", param.getType(), param.getAlgorithmName());
            throw new BusinessException("calculation-period-error");
        }
        log.info("powerJob定时任务创建成功, jobId: {}", jobIdList);
        return jobIdList;
    }

    private PowerJobRequestParam getJobParams(AlgorithmInfo algorithmInfo, String cronExpression, int jobCount) {
        PowerJobRequestParam powerJobRequest = new PowerJobRequestParam();
        powerJobRequest.setJobName(String.format("%s(%d)", algorithmInfo.getAlgorithmName(), jobCount));
        powerJobRequest.setJobParams(JSON.toJSONString(algorithmInfo));
        // TimeExpressionType = CRON
        powerJobRequest.setTimeExpressionType("CRON");
        powerJobRequest.setTimeExpression(cronExpression);
        powerJobRequest.setProcessorInfo(TASK_PROCESSOR);
        powerJobRequest.setEnable(true);

        return powerJobRequest;
    }

    /**
     * 新增异常日志记录
     *
     * @param param
     */
    public void addRecordMethod(Object param) {
        String name = "";
        if (param != null && param instanceof AlgorithmInfo) {
            AlgorithmInfo info = (AlgorithmInfo) param;
            name = info.getAlgorithmName();
        }
        String nickName = SecurityUtils.getUser().getNickName();
        MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
        logClientSimple.addBusinessLog(LogLevel.ERROR.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.add.getCname() + PageDescEnum.Algorithm.getDesc(),
                        OperatorTypeDescEnum.add.getCname() + name, Constants.OperationStatus.FAILED}, LocaleContextHolder.getLocale()));

    }

}
